package xyz.xuminghai.javafx_learn.scene.effect;

import javafx.application.Application;
import javafx.geometry.Bounds;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.effect.BlurType;
import javafx.scene.effect.InnerShadow;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
import javafx.stage.Stage;

/**
 * 2023/6/5 2:57 星期一<br/>
 * 内阴影
 * 文字立体效果
 *
 * @author xuMingHai
 */
public class InnerShadowApp extends Application {

    private final BorderPane root = new BorderPane();


    public static void main(String[] args) {
        Application.launch(args);
    }

    @Override
    public void init() {
        Text text = new Text("InnerShadow");
        InnerShadow innerShadow = new InnerShadow();

        text.setEffect(innerShadow);
        text.setFont(Font.font(50.0));
        VBox vBox = new VBox(30.0,
                blurTypeParameter(innerShadow),
                colorParameter(innerShadow),
                radiusParameter(innerShadow),
                widthParameter(innerShadow),
                heightParameter(innerShadow),
                chokeParameter(innerShadow),
                offsetXParameter(innerShadow, text),
                offsetYParameter(innerShadow, text)
        );
        vBox.setAlignment(Pos.CENTER);

        root.setCenter(text);
        root.setRight(vBox);
    }

    private HBox blurTypeParameter(InnerShadow innerShadow) {
        Label label = new Label("BlurType");
        label.setFont(Font.font(20.0));
        label.setTooltip(new Tooltip("""
                用于模糊阴影的算法。
                        Min: n/a
                        Max: n/a
                    Default: BlurType.THREE_PASS_BOX
                   Identity: n/a
                                
                默认值：THREE_PASS_BOX
                """));


        ToggleGroup toggleGroup = new ToggleGroup();

        RadioButton radioButton1 = new RadioButton("ONE_PASS_BOX");
        radioButton1.setUserData(BlurType.ONE_PASS_BOX);
        radioButton1.setToggleGroup(toggleGroup);
        radioButton1.setTooltip(new Tooltip("""
                盒式过滤器的单通道用于模糊阴影。
                """));

        RadioButton radioButton2 = new RadioButton("TWO_PASS_BOX");
        radioButton2.setToggleGroup(toggleGroup);
        radioButton2.setUserData(BlurType.TWO_PASS_BOX);
        radioButton2.setTooltip(new Tooltip("""
                盒式过滤器的两遍用于模糊阴影以获得稍微平滑的效果。
                """));

        RadioButton radioButton3 = new RadioButton("THREE_PASS_BOX");
        radioButton3.setSelected(true);
        radioButton3.setToggleGroup(toggleGroup);
        radioButton3.setUserData(BlurType.THREE_PASS_BOX);
        radioButton3.setTooltip(new Tooltip("""
                使用盒式滤波器的三遍来模糊阴影，以获得几乎与高斯滤波器一样平滑的效果。
                """));

        RadioButton radioButton4 = new RadioButton("GAUSSIAN");
        radioButton4.setToggleGroup(toggleGroup);
        radioButton4.setUserData(BlurType.GAUSSIAN);
        radioButton4.setTooltip(new Tooltip("""
                高斯模糊内核用于以非常高的质量模糊阴影，以获得几乎与高斯滤波器一样平滑的效果。
                """));


        toggleGroup.selectedToggleProperty().addListener((observable, oldValue, newValue) -> {
            System.out.println("newBlurType = " + newValue);
            innerShadow.setBlurType((BlurType) newValue.getUserData());
        });


        return new HBox(20.0, label,
                new VBox(10.0,
                        radioButton1,
                        radioButton2,
                        radioButton3,
                        radioButton4
                )
        );
    }

    private HBox colorParameter(InnerShadow innerShadow) {
        Label label = new Label("Color");
        label.setFont(Font.font(20.0));
        label.setTooltip(new Tooltip("""
                阴影Color。
                        Min: n/a
                        Max: n/a
                    Default: Color.BLACK
                   Identity: n/a
                                
                默认值：黑色的
                """));

        ColorPicker colorPicker = new ColorPicker(Color.BLACK);
        colorPicker.setOnAction(event -> {
            System.out.println("colorPicker.getValue() = " + colorPicker.getValue());
            innerShadow.setColor(colorPicker.getValue());
        });

        return new HBox(20.0, label, colorPicker);
    }

    private HBox radiusParameter(InnerShadow innerShadow) {
        Label label = new Label("Radius");
        label.setFont(Font.font(20.0));
        label.setTooltip(new Tooltip("""
                阴影模糊内核的半径。该属性控制阴影传播到源像素每一侧的距离。
                设置半径相当于将width和height属性都设置为(2 * radius + 1)值。
                        Min:   0.0
                        Max: 127.0
                    Default:  10.0
                   Identity:   0.0
                                
                默认值：10.0
                """));

        Spinner<Double> spinner = new Spinner<>(0.0, 127.0, 10.0);
        spinner.setEditable(true);

        spinner.valueProperty().addListener((observable, oldValue, newValue) -> {
            System.out.println("newRadius = " + newValue);
            innerShadow.setRadius(newValue);
        });

        return new HBox(20.0, label, spinner);
    }

    private HBox widthParameter(InnerShadow innerShadow) {
        Label label = new Label("Width");
        label.setFont(Font.font(20.0));
        label.setTooltip(new Tooltip("""
                阴影模糊内核的水平尺寸。此属性控制模糊算法分布单个像素阴影的总区域的水平大小。
                小于1.0值不会分布到原始像素之外，因此对阴影没有模糊效果。
                        Min:   0.0
                        Max: 255.0
                    Default:  21.0
                   Identity:  <1.0

                默认值：21.0
                """));

        Spinner<Double> spinner = new Spinner<>(0.0, 255.0, 21.0);
        spinner.setEditable(true);

        spinner.valueProperty().addListener((observable, oldValue, newValue) -> {
            System.out.println("newWidth = " + newValue);
            innerShadow.setWidth(newValue);
        });

        return new HBox(20.0, label, spinner);
    }

    private HBox heightParameter(InnerShadow innerShadow) {
        Label label = new Label("Height");
        label.setFont(Font.font(20.0));
        label.setTooltip(new Tooltip("""
                阴影模糊内核的垂直尺寸。此属性控制模糊算法在其上分布单个像素的阴影的总区域的垂直大小。
                小于1.0值不会分布到原始像素之外，因此对阴影没有模糊效果。
                        Min:   0.0
                        Max: 255.0
                    Default:  21.0
                   Identity:  <1.0
                                
                默认值：21.0
                """));

        Spinner<Double> spinner = new Spinner<>(0.0, 255.0, 21.0);
        spinner.setEditable(true);

        spinner.valueProperty().addListener((observable, oldValue, newValue) -> {
            System.out.println("newHeight = " + newValue);
            innerShadow.setHeight(newValue);
        });

        return new HBox(20.0, label, spinner);
    }

    private HBox chokeParameter(InnerShadow innerShadow) {
        Label label = new Label("Choke");
        label.setFont(Font.font(20.0));
        label.setTooltip(new Tooltip("""
                阴影的窒息。扼流圈是源材料贡献为 100% 的半径部分。
                半径的剩余部分将具有由模糊内核控制的贡献。
                0.0的抑制将导致阴影的分布完全由模糊算法确定。
                1.0的扼流圈将导致阴影从边缘到半径极限向内坚实生长，
                并非常尖锐地截止半径内的透明度。
                        Min: 0.0
                        Max: 1.0
                    Default: 0.0
                   Identity: 0.0
                                
                默认值：0.0
                """));

        Spinner<Double> spinner = new Spinner<>(0.0, 1.0, 0.0, 0.01);
        spinner.setEditable(true);

        spinner.valueProperty().addListener((observable, oldValue, newValue) -> {
            System.out.println("newChoke = " + newValue);
            innerShadow.setChoke(newValue);
        });

        return new HBox(20.0, label, spinner);
    }

    private HBox offsetXParameter(InnerShadow innerShadow, Text text) {
        Label label = new Label("OffsetX");
        label.setFont(Font.font(20.0));
        label.setTooltip(new Tooltip("""
                x 方向上的阴影偏移（以像素为单位）。
                        Min: n/a
                        Max: n/a
                    Default: 0.0
                   Identity: 0.0
                                
                默认值：0.0
                """));

        Bounds layoutBounds = text.getLayoutBounds();
        double width = layoutBounds.getWidth();
        Spinner<Double> spinner = new Spinner<>(-width, width, 0.0);
        spinner.setEditable(true);

        spinner.valueProperty().addListener((observable, oldValue, newValue) -> {
            System.out.println("newOffsetX = " + newValue);
            innerShadow.setOffsetX(newValue);
        });

        return new HBox(20.0, label, spinner);
    }

    private HBox offsetYParameter(InnerShadow innerShadow, Text text) {
        Label label = new Label("OffsetY");
        label.setFont(Font.font(20.0));
        label.setTooltip(new Tooltip("""
                y 方向上的阴影偏移（以像素为单位）。
                        Min: n/a
                        Max: n/a
                    Default: 0.0
                   Identity: 0.0
                                
                默认值：0.0
                """));

        Bounds layoutBounds = text.getLayoutBounds();
        double height = layoutBounds.getHeight();
        Spinner<Double> spinner = new Spinner<>(-height, height, 0.0);
        spinner.setEditable(true);

        spinner.valueProperty().addListener((observable, oldValue, newValue) -> {
            System.out.println("newOffsetY = " + newValue);
            innerShadow.setOffsetY(newValue);
        });

        return new HBox(20.0, label, spinner);
    }


    @Override
    public void start(Stage primaryStage) {
        primaryStage.setTitle(getClass().getSimpleName());
        Scene scene = new Scene(root, 800, 600);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

}
